
#include "stdafx.h"
#include <shlobj.h>
#include "resource.h"
#include "control.h"
#include "global.h"
#include "wallpaperhelper.hpp"

Control::Control(void)
{
}

Control::~Control(void)
{
}

void Control::Init()
{
	int borderWidth = 0;
	RECT windowRect;
	RECT clientRect;
	GetWindowRect(Global::instance().hwnd, &windowRect);
	GetClientRect(Global::instance().hwnd, &clientRect);
	borderWidth = (windowRect.right-windowRect.left) - (clientRect.right-clientRect.left);

	int width = THUMBNAIL_WIDTH*IMAGECOUNT_X + THUMBNAIL_MARGIN_WIDTH*(IMAGECOUNT_X+1) + borderWidth;
	int height = THUMBNAIL_HEIGHT*IMAGECOUNT_Y + THUMBNAIL_MARGIN_HEIGHT*(IMAGECOUNT_Y+1) + TITLEBAR_HEIGHT;
	RECT rect = {0, 0, width, height};
	MoveWindow(Global::instance().hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, FALSE);

	WCHAR appdatapath[MAX_PATH];
	SHGetSpecialFolderPath(Global::instance().hwnd, appdatapath, CSIDL_PERSONAL, FALSE);
	std::wstring wallpaperpath = appdatapath;
	wallpaperpath += L"\\Tencent Files\\QPlus\\All Users\\Wallpaper";
	m_picbox.Load(wallpaperpath.c_str());

	m_titlebar.Load();

	WallpaperHelper::instance().RememberWallpaper();

	m_brush = CreateSolidBrush(RGB(0, 0x66, 0xcc));

	Layout();
}

void Control::UnInit()
{
	DeleteObject(m_brush);
	FreeMemBitmap();
}

LRESULT Control::DispatchMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	LRESULT ret = 0;
	Message msg = {hWnd, message, wParam, lParam};
	m_messageStack.push(msg);

	switch (message)
	{
	case WM_PAINT:
		OnPaint();
		break;
	case WM_MOUSEMOVE:
		OnMouseMove((UINT)wParam, LparamToPoint(lParam));
		break;
	case WM_LBUTTONDOWN:
		OnLButtonDown((UINT)wParam, LparamToPoint(lParam));
		break;
	case WM_LBUTTONUP:
		OnLButtonUp((UINT)wParam, LparamToPoint(lParam));
		break;
	case WM_SIZE:
		OnSize((UINT)wParam, LOWORD(lParam), HIWORD(lParam));
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	case WM_ERASEBKGND:
		break;
	default:
		ret = DefWindowProc(hWnd, message, wParam, lParam);
	}

	m_messageStack.pop();
	return ret;
}

void Control::OnPaint()
{
	Draw();
	DefaultMessageProcess();
}

void Control::OnMouseMove(UINT nFlags, POINT point)
{
	m_picbox.MouseMove(point);
	m_titlebar.MouseMove(point);

	DefaultMessageProcess();
}

void Control::OnLButtonDown(UINT nFlags, POINT point)
{
	if (!m_picbox.MouseDown(point) && !m_titlebar.MouseDown(point))
	{
		SendMessage(Global::instance().hwnd, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));
	}

	DefaultMessageProcess();
}

void Control::OnLButtonUp(UINT nFlags, POINT point)
{
	m_picbox.MouseUp(point);
	m_titlebar.MouseUp(point);

	DefaultMessageProcess();
}

void Control::OnSize(UINT nType, int cx, int cy)
{
	RECT clientRect;
	GetClientRect(Global::instance().hwnd, &clientRect);

	FreeMemBitmap();
	CreateMemBitmap();

	Layout();

	SCROLLINFO si = {sizeof(si)};
	GetScrollInfo(Global::instance().hwnd, SB_VERT, &si);
	si.nMin = 0;
	si.nMax = m_picbox.GetContentHeight();
	si.nPage = m_picbox.GetRect().bottom, m_picbox.GetRect().top;
	si.nTrackPos = 10;
	si.nPos  = min(si.nPos, si.nMax);
	SetScrollInfo(Global::instance().hwnd, SB_VERT, &si, FALSE);

	m_picbox.ScrollTo(si.nPos);

	DefaultMessageProcess();
}

void Control::CreateMemBitmap()
{
	HDC dc = GetDC(Global::instance().hwnd);

	RECT clientRect;
	GetClientRect(Global::instance().hwnd, &clientRect);

	m_memdc = CreateCompatibleDC(dc);
	m_membitmap = CreateCompatibleBitmap(dc, clientRect.right - clientRect.left, clientRect.bottom - clientRect.top);
	SelectObject(m_memdc, m_membitmap);

	ReleaseDC(Global::instance().hwnd, dc);
	dc = NULL;
}

void Control::FreeMemBitmap()
{
	if (m_membitmap != NULL)
	{
		DeleteObject(m_membitmap);
		m_membitmap = NULL;
	}

	if (m_memdc != NULL)
	{
		DeleteDC(m_memdc);
		m_memdc = NULL;
	}
}

POINT Control::LparamToPoint(LPARAM lParam)
{
	POINT point = {LOWORD(lParam), HIWORD(lParam)};
	return point;
}

void Control::Draw()
{
	RECT rect;
	GetClientRect(Global::instance().hwnd, &rect);
	FillRect(m_memdc, &rect, m_brush);

	m_picbox.Draw(m_memdc);
	m_titlebar.Draw(m_memdc);

	HDC dc = GetDC(Global::instance().hwnd);
	BitBlt(dc, 0, 0, rect.right-rect.left, rect.bottom-rect.top, m_memdc, 0, 0, SRCCOPY);
	ReleaseDC(Global::instance().hwnd, dc);
	dc = NULL;
}

void Control::Layout()
{
	RECT rect;

	RECT clientRect;
	GetClientRect(Global::instance().hwnd, &clientRect);

	rect = clientRect;
	rect.bottom = rect.top + TITLEBAR_HEIGHT;
	m_titlebar.SetRect(rect);

	rect.left = clientRect.left + THUMBNAIL_MARGIN_WIDTH;
	rect.top = clientRect.top + TITLEBAR_HEIGHT;
	rect.right = clientRect.right - THUMBNAIL_MARGIN_WIDTH;
	rect.bottom = clientRect.bottom - THUMBNAIL_MARGIN_HEIGHT;
	m_picbox.SetRect(rect);
}

LRESULT Control::DefaultMessageProcess()
{
	Message msg = m_messageStack.top();
	return DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
}
